<template>
  <div class="flow-process-container" :style="{ background: background }" v-if="data.length">
    <flow-process-action-bar :scale.sync="scale" v-if="showScaleBar"></flow-process-action-bar>
    <div
      class="flow-process-container__content"
      :class="{ vertical: vertical, 'transform-origin-center': scale <= 100 }"
      :style="{ transform: `scale(${scale / 100})` }"
    >
      <biz-flow-process-node
        v-for="(node, index) in data"
        :key="node.id"
        :nodeList="data"
        :data="node"
        :nextData="data[index + 1]"
      ></biz-flow-process-node>
    </div>
  </div>
</template>

<script>
import emitter from './emit'
import { generateNode } from './utils'
import { store, defaultNodeList } from './constant'
import ActionBar from './components/ActionBar.vue'
// TODO  相关线的颜色问题
export default {
  name: 'biz-flow-process-chart',
  components: {
    [ActionBar.name]: ActionBar
  },
  model: {
    prop: 'data',
    event: 'change'
  },
  props: {
    data: {
      type: Array,
      default() {
        return []
      }
    },
    customCreateNode: {
      type: Function
    },
    customCreateConditionBranchNode: {
      type: Function
    },
    beforeDeleteNode: {
      type: Function
    },
    beforeAddNode: {
      type: Function
    },
    background: {
      type: String,
      default: ''
    },
    readonly: {
      type: Boolean,
      default: false
    },
    nodeTypeList: {
      type: Array
    },
    vertical: {
      type: Boolean,
      default: false
    },
    showScaleBar: {
      type: Boolean,
      default: true
    },
    customCreateNodeId: {
      type: Function
    },
    nodeThroughList: {
      type: Array,
      default: ()=> []
    },
    currentNode: {
      type: Object,
      default: ()=> {}
    },
  },
  data() {
    return {
      scale: 100
    }
  },
  watch: {
    nodeThroughList(newValue) {
      this.filterInitThroughNode(newValue)
    }
  },
  created() {
    store.readonly = this.readonly
    store.nodeTypeList = this.nodeTypeList
    store.vertical = this.vertical
    store.customCreateNodeId = this.customCreateNodeId
    this.filterInitThroughNode(this.nodeThroughList)
    // if (this.data.length <= 0) {
    //   this.data.push(...defaultNodeList)
    // }
    emitter.on('add-node-type-click', this.onAddNodeTypeClick)
    emitter.on('delete-node-click', this.onNodeDeleteClick)
    emitter.on('add-condition-branch-click', this.onAddConditionBranchClick)
    emitter.on('node-content-click', this.onNodeContentClick)
    emitter.on('add-node-popover-type-click', this.onAddNodePopoverTypeClick)
  },
  beforeDestroy() {
    emitter.off('add-node-type-click', this.onAddNodeTypeClick)
    emitter.off('delete-node-click', this.onNodeDeleteClick)
    emitter.off('add-condition-branch-click', this.onAddConditionBranchClick)
    emitter.off('node-content-click', this.onNodeContentClick)
    emitter.off('add-node-popover-type-click', this.onAddNodePopoverTypeClick)
  },
  methods: {
    filterInitThroughNode(nodeThroughList) {
      store.nodeThroughIds = nodeThroughList.filter(item=> !item.isCurrent).map(item=> item.nodeTemplateId)
      store.currentNodeIds = nodeThroughList.filter(item=> item.isCurrent).map(item=> item.nodeTemplateId)
    },

    async onAddNodeTypeClick(nodeList, nodeData, nextData, type) {

      let newNode = null
    
      if (this.customCreateNode) {
        newNode = this.customCreateNode(nodeList, nodeData, nextData, type)
        // 校验公共节点是否可以添加
        if(newNode?.isCommon === 1 && this.beforeAddNode){
          const isCheckSuccess = await this.beforeAddNode(newNode)
          if(!isCheckSuccess) return
        }
      }
      if (!newNode) {
        newNode = generateNode(type.type)
      }
      this.addNode(nodeList, nodeData, nextData, newNode)
      this.$emit('add-node', newNode)
    },

    addNode(nodeList, nodeData, nextData, newNode) {
      if (nodeList) {
        let index = this.findNodeIndex(nodeList, nodeData)
        nodeList.splice(index + 1, 0, newNode)
      } else {
        nodeData.nodeList.unshift(newNode)
      }
    },

    onNodeDeleteClick(...args) {
      if (this.beforeDeleteNode) {
        this.beforeDeleteNode(...args).then(() => {
          this.deleteNode(...args)
        })
      } else {
        this.deleteNode(...args)
        this.$emit('delete-node', args[3])
      }
    },

    deleteNode(nodeList, childrenList, belongConditionNodeData, nodeData) {
      if (nodeList) {
        let index = this.findNodeIndex(nodeList, nodeData)
        nodeList.splice(index, 1)
        if(index > 1) {
          nodeList[index-1].targetId = nodeList[index].id
        }
        const childrenListItemIndex = Array.isArray(childrenList) ? childrenList.findIndex(item=> item.nodeList.length === 0) : -1
        if(childrenListItemIndex > -1) {
          childrenList.splice(childrenListItemIndex, 1)
        }

        if (nodeList.length <= 1 && childrenList.length <=1) {
          this.removeNodeFromData(belongConditionNodeData)
        }
      } else if (childrenList) {
        let index = this.findNodeIndex(childrenList, nodeData)
        childrenList.splice(index, 1)
        if (childrenList.length <= 1) {
          this.removeNodeFromData(belongConditionNodeData)
        }
      }
    },

    onAddConditionBranchClick(nodeData) {
      let newNode = null
      if (this.customCreateConditionBranchNode) {
        newNode = this.customCreateConditionBranchNode(nodeData)
      }
      if (!newNode) {
        newNode = generateNode('normal', '条件', '条件内容')
      }
      nodeData.children.push(newNode)
      this.$emit('add-condition-branch', newNode)
    },

    onNodeContentClick(...args) {
      this.$emit('node-content-click', ...args)
    },
    /** 点击加号 */
    onAddNodePopoverTypeClick(type, addNodeTypeList) {
      this.$emit('handleNodePopoverTypeClick', type, addNodeTypeList)
    },
    findNodeIndex(list, node) {
      return list.findIndex(item => {
        return item === node
      })
    },

    removeNodeFromData(nodeData) {
      let walk = arr => {
        for (let i = 0; i < arr.length; i++) {
          let node = arr[i]
          if (node === nodeData) {
            arr.splice(i, 1)
            return true
          }
          let res = false
          if (node.children && node.children.length > 0) {
            res = walk(node.children)
          }
          if (!res && node.nodeList && node.nodeList.length > 0) {
            res = walk(node.nodeList)
          }
          if (res) {
            break
          }
        }
      }
      walk(this.data)
    }
  }
}
</script>

<style lang="scss" scoped>
.flow-process-container {
  width: 100%;
  height: 100%;
  overflow: auto;
  box-sizing: border-box;

 * {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
  }

  &__content{
    display: flex;
    align-items: center;
    padding: 20px;
    // min-width: 100%;
    // min-height: 100%;
    // width: max-content;
    // height: max-content;
    // transform-origin: left top;

    &.transform-origin-center {
      transform-origin: center center;
    }

    &.vertical {
      flex-direction: column;
      justify-content: start;
    }
  }
}
.cursor-default {
  cursor: default !important;
}
.flow-process-tooltip{
  max-width: 280px;
}
</style>
